import os
import shutil
import threading
import zlib

import cv2
from PIL import Image


def renamefile(url, old_str, new_str, last_code):
    old_str_split = old_str.split("&&")
    for dirpath, dirnames, filenames, in os.walk(url):
        for filename in filenames:
            try:
                inputfilename = os.path.join(dirpath, filename)
                if len(last_code) > 0 and not filename.__contains__(last_code):
                    continue
                new_filename = filename[0:filename.rfind(".")]
                last_code = filename[filename.rfind("."):]
                for str in old_str_split:
                    new_filename = new_filename.replace(str, new_str)
                new_filename += last_code
                outfilename = os.path.join(dirpath, new_filename)
                os.rename(inputfilename, outfilename)
                print("old_name:{}-->new_name:{}".format(inputfilename, outfilename))
            except FileExistsError as f:
                print(f)
                continue


class Compress_Pic_or_Video(object):
    """
    图片和视频压缩类
    提供图片和视频的压缩功能，支持批量处理
    """

    def __init__(self, filePath, inputName, outputName, new_dir=""):
        """
        初始化压缩类
        
        Args:
            filePath: 文件所在目录路径
            inputName: 输入文件名
            outputName: 输出文件名
            new_dir: 新目录名称，默认为空
        """
        self.new_dir = new_dir  # 新目录名称
        self.filePath = filePath  # 文件所在目录路径
        self.inputName = inputName  # 输入文件名
        # self.system_ = platform.platform().split("-", 1)[0]
        # if self.system_ == "Windows":
        #     self.filePath = (self.filePath + "\\") if self.filePath.rsplit("\\", 1)[-1] else self.filePath
        # elif self.system_ == "Linux":
        #     self.filePath = (self.filePath + "/") if self.filePath.rsplit("/", 1)[-1] else self.filePath
        self.fileInputPath = os.path.join(self.filePath, inputName)
        self.fileOutPath = os.path.join(self.filePath + "-" + self.new_dir, outputName)

    @property
    def is_picture(self):
        """
        判断文件是否为图片
        
        Returns:
            bool: 如果是图片返回True，否则返回False
        """
        # 支持的图片格式集合
        picSuffixSet = {"BMP", "GIF", "JPEG", "TIFF", "PNG", "SVG", "PCX", "WMF", "EMF", "LIC", "EPS", "TGA", "JPG"}
        # 获取文件后缀并转换为大写
        suffix = self.fileInputPath.rsplit(".", 1)[-1].upper()
        # 判断后缀是否在支持的图片格式集合中
        return suffix in picSuffixSet

    @property
    def is_video(self):
        """
        判断文件是否为视频
        
        Returns:
            bool: 如果是视频返回True，否则返回False
        """
        # 支持的视频格式集合
        videoSuffixSet = {"WMV", "ASF", "ASX", "RM", "RMVB", "MP4", "3GP", "MOV", "M4V", "AVI", "DAT", "MKV", "FIV",
                          "VOB"}
        # 获取文件后缀并转换为大写
        suffix = self.fileInputPath.rsplit(".", 1)[-1].upper()
        # 判断后缀是否在支持的视频格式集合中
        return suffix in videoSuffixSet

    def SavePic(self):
        """
        保存压缩后的图片
        
        Returns:
            tuple or bool: 如果压缩成功返回(输出路径, 文件大小)，如果文件小于50K返回True
        """
        # 获取图片大小（KB）
        fpsize = os.path.getsize(self.fileInputPath) / 1024
        # 如果图片大于50KB才进行压缩
        if fpsize >= 50.0:
            # 打开图片
            im = Image.open(self.fileInputPath)
            # 将图片转换为字节流
            imBytes = im.tobytes()
            # 使用zlib压缩字节流
            imBytes = zlib.compress(imBytes, 5)
            # 从压缩后的字节流创建新图片
            im2 = Image.frombytes('RGB', im.size, zlib.decompress(imBytes))
            # 保存图片
            if self.fileOutPath:
                # 保存到新路径
                im2.save(self.fileOutPath)
                return (self.fileOutPath, os.path.getsize(self.fileOutPath))
            else:
                # 覆盖原图
                im2.save(self.fileInputPath)
                return (self.fileInputPath, os.path.getsize(self.fileInputPath))
        else:
            # 文件太小，不压缩
            return True

    def Compress_Video(self):
        """
        保存压缩后的视频
        
        Returns:
            bool or tuple: 压缩成功返回True，失败返回(错误码, 错误信息)
        """
        # 创建必要的目录
        if not os.path.exists(self.filePath + "-" + self.new_dir):
            os.mkdir(self.filePath + "-" + self.new_dir)
        if not os.path.exists(self.filePath + "-old"):
            os.mkdir(self.filePath + "-old")

        # 获取视频信息
        video = cv2.VideoCapture(self.fileInputPath)
        width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH))  # 视频宽度
        height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))  # 视频高度
        bitrate = int(video.get(cv2.CAP_PROP_BITRATE))  # 视频比特率
        video.release()

        # 限制最大比特率
        if bitrate > 1500:
            bitrate = 1500

        # 如果分辨率小于等于1280x1280，直接复制
        elif width <= 1280 and height <= 1280:
            shutil.move(self.fileInputPath, self.fileOutPath)
            return True

        # 构建ffmpeg压缩命令
        compress = f"ffmpeg -y -i {self.fileInputPath} -c:v h264 -b:v {bitrate}k -bufsize {bitrate}k -preset slow -crf 25 -c:a copy -b:a 32k -strict -5 -max_muxing_queue_size 1024 {self.fileOutPath}"

        # 如果分辨率大于1280，添加缩放参数
        if (width >= height and width > 1280) or (height > width and height > 1280):
            compress = f"ffmpeg -y -i {self.fileInputPath} -c:v h264 -vf scale={width / 2}:-1 -b:v {bitrate}k -bufsize {bitrate}k -preset slow -crf 25 -c:a copy -b:a 32k -strict -5 -max_muxing_queue_size 1024 {self.fileOutPath}"

        # 执行压缩命令
        isRun = os.system(compress)

        # 检查压缩是否成功
        if isRun != 0:
            return (isRun, "没有安装ffmpeg")

        # 比较压缩前后的文件大小
        fpsize_old = os.path.getsize(self.fileInputPath)
        fpsize_new = os.path.getsize(self.fileOutPath)

        # 如果压缩后文件更大，使用原文件
        if fpsize_old < fpsize_new:
            shutil.move(self.fileInputPath, self.fileOutPath)
        else:
            # 移动原文件到old目录
            shutil.move(self.fileInputPath, os.path.join(self.filePath + "-old", self.inputName))
        return True

    def Compress_Picture(self):
        """
        异步压缩图片
        使用线程异步执行图片压缩
        """
        thr = threading.Thread(target=self.SavePic)
        thr.start()


if __name__ == "__main__":
    # b = sys.argv[1:]	#测试压缩
    # savepic = Compress_Pic_or_Video(b[0],b[1],b[2])
    dir_path = r'E:\ai\电报'
    flag = 2
    if flag == 1:
        old_str = r"《&&: && &&。&&，&& &&!&&》&&#&&\&&&;&&[&&]&&♥&&－&&?&&？&&【&&】&&+&&⁉️&&～&&〖&&〗&&『&&』&&/&&-&&！&& &&の&&(&&)&&（&&）&&，&&,&&“&&”&&：" \
                  r"&&⋯&&@&&▌&&／&&、&&✿&&の&&...&&_&&™"
        new_str = ""
        last_code = ""
        renamefile(dir_path, old_str, new_str, last_code)
    if flag == 2:
        new_dir = "compress"
        for root, dirs, files in os.walk(dir_path):
            total = len(files)
            count = 0
            for file in files:
                if file.lower().endswith(".cfg") or file.lower().endswith(".gif") or file.lower().endswith(
                        ".jpg") or file.lower().endswith(".png"):
                    count += 1
                    print("跳过 {} 已完成 {}/{}".format(file, count, total))
                    continue
                out_file_name = file
                if not out_file_name.endswith(".mp4"):
                    out_file_name = out_file_name.replace(".", '') + '.mp4'
                fpsize = os.path.getsize(os.path.join(root, file)) / (1024 * 1024)
                if fpsize <= 10.0:  # 大于?MB的视频需要压缩
                    count += 1
                    print("跳过 {} 已完成 {}/{}".format(file, count, total))
                    continue
                if root.__contains__('-compress') or root.__contains__('-old'):
                    count += 1
                    continue
                savepic = Compress_Pic_or_Video(root, file, out_file_name, new_dir)
                savepic.Compress_Video()
                count += 1
                print("压缩 {} 已完成 {}/{}".format(file, count, total))
